import { OnInit, Component, OnChanges, SimpleChanges, Input, Output, EventEmitter, ViewChildren, QueryList } from '@angular/core';
import { Song, LyricLine } from 'src/app/routes/entity';
import { PanelScrollComponent } from '../panel-scroll/panel-scroll.component';
import { timer, Subscription, Subject } from 'rxjs';
import { SongService } from '../../service/song.service';
import { LyricParseService } from '../../service/lyric-parse.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-music-play-panel',
  templateUrl: './music-play-panel.component.html',
  styleUrls: ['./music-play-panel.component.less']
})
export class MusicPlayPanelComponent implements OnInit, OnChanges {

  @Input()
  playing: boolean;

  @Input()
  songList: Song[];

  @Input()
  currentSong: Song;

  @Input()
  showPanel = false;

  @Output()
  onClose: EventEmitter<void> = new EventEmitter<void>();

  @Output()
  onChangeSong: EventEmitter<number> = new EventEmitter<number>();

  @Output()
  onDeleteSong: EventEmitter<number> = new EventEmitter<number>();

  @Output()
  onClearSongList: EventEmitter<void> = new EventEmitter<void>();

  @ViewChildren(PanelScrollComponent)
  private panelScrollList: QueryList<PanelScrollComponent>;

  scrollY = 0;

  currentIndex: number;

  /** 歌词行参数 */
  currentLyricLines: LyricLine[];
  currentLineNum: number;
  lyricScrollTimer: Subscription;
  lyricScrollHandler: Subject<number> = new Subject<number>();
  startStamp: number;
  pauseStamp: number;
  lyricElemRefs: NodeList;
  lyricScrollStartLine: number;

  constructor(
    private songService: SongService,
    private lyricParseService: LyricParseService,
    private router: Router
  ) { }

  ngOnInit(): void {

  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes['playing']) {
      if (!changes['playing'].firstChange) {
        if (this.currentLyricLines && this.currentLyricLines.length > 0) {
          this.togglePlay();
        }
      }
    }

    if (changes['songList']) {
      if (this.currentSong) {
        // 更新当前播放歌曲的索引
        this.updateCurrentIndex();
      }
    }

    if (changes['currentSong']) {
      if (this.currentSong) {
        // 更新当前播放歌曲的索引
        this.updateCurrentIndex();
        // 更新歌词
        this.updateLyric(this.currentSong.id);
        if (this.showPanel) {
          this.scrollToCurrentSong();
        }
      } else {
        // 清空歌词列表数据
        this.resetLyricData();
      }
    }

    if (changes['showPanel']) {
      if (!changes['showPanel'].firstChange && this.showPanel) {
        // 刷新歌曲列表滚动
        this.panelScrollList.first.resfreshPanelScroll();
        // 刷新歌词滚动
        this.panelScrollList.last.resfreshPanelScroll();
        timer(80).subscribe(() => {
          if (this.currentSong) {
            this.scrollToCurrentSong(0);
          }
          if (this.lyricElemRefs) {
            this.scrollToCurrentLyric(0);
          }
        });
      }
    }
  }

  /** 音乐面板关闭事件 */
  onCloseEvent(): void {
    this.onClose.emit();
  }

  /** 改变音乐 */
  onChangeSongEvent(index: number): void {
    this.onChangeSong.emit(index);
  }

  /** 删除单个歌单 */
  onDeleteSongEvent(songId: number): void {
    this.onDeleteSong.emit(songId);
  }

  routerToSingerDetail(event: MouseEvent, singerId: string): void {
    event.stopPropagation();
    this.showPanel = false;
    this.router.navigateByUrl(`/music/singers/${singerId}/detail`);
  }

  routerToSongDetail(event: MouseEvent, songId: string): void {
    event.stopPropagation();
    this.showPanel = false;
    this.router.navigateByUrl(`/music/songs/${songId}/detail`);
  }

  /** 清空歌单列表 */
  onClearSongListEvent(): void {
    this.onClearSongList.emit();
  }

  skipLyric(time: number): void {
    if (this.currentLyricLines) {
      this.lyricSynchronousScrolled(this.currentLyricLines, time);
    }
  }

  /** 更新当前 */
  private updateCurrentIndex(): void {
    this.currentIndex = this.songList.findIndex(e => e.id === this.currentSong.id);
  }

  /**
   * 根据歌单编号更新歌词
   *
   * @param songId 歌单编号
   */
  private updateLyric(songId: number): void {
    this.resetLyricData();
    this.songService.getLyric(songId).subscribe(
      res => {
        this.currentLyricLines = this.lyricParseService.parseLyric(res);
        this.lyricScrollStartLine = res.tlyric ? 1 : 3;
        this.handleLyricScroll();
        this.panelScrollList.last.scrollTo(0, 0);
        if (this.playing) {
          this.lyricSynchronousScrolled(this.currentLyricLines);
        }
      }
    );
  }

  /**
   * 歌词同步滚动
   *
   * @param lyricLines 歌词行集合
   * @param startTime 开始时间
   */
  private lyricSynchronousScrolled(lyricLines: LyricLine[], startTime: number = 0, isSkip = false): void {
    if (!lyricLines.length) {
      return;
    }
    const currentNum = this.findlLyricLineIndex(lyricLines, startTime);
    // 获取开始时间戳
    this.startStamp = Date.now() - startTime;
    if (!isSkip) {
      this.callLyricScrollHandler(currentNum - 1);
    }
    if (currentNum < lyricLines.length) {
      this.clearTimer();
      this.keepLyricScroll(lyricLines, currentNum);
    }
  }

  /**
   * 根据播放时间获取歌词行索引
   *
   * @param time 播放时间
   */
  private findlLyricLineIndex(lyricLines: LyricLine[], time: number): number {
    const index = lyricLines.findIndex(e => e && e.time >= time);
    return index === -1 ? lyricLines.length - 1 : index;
  }

  /**
   * 保持歌词滚动
   *
   * @param lyricLines 歌词行集合
   * @param currentNum 当前行数
   * @param startStamp 开始时间戳
   */
  private keepLyricScroll(lyricLines: LyricLine[], currentNum: number): void {
    const line = lyricLines[currentNum];
    // 如果当前行是 null，则直接跳过
    const delay = line ? line.time - (Date.now() - this.startStamp) : 1;
    this.lyricScrollTimer = timer(delay).subscribe(() => {
      this.callLyricScrollHandler(currentNum++);
      if (currentNum < lyricLines.length && this.playing) {
        this.keepLyricScroll(lyricLines, currentNum);
      }
    });
  }

  /**
   * 执行歌词滚动处理
   * 
   * @param index 歌词行索引
   */
  private callLyricScrollHandler(index: number): void {
    if (index > 0) {
      this.lyricScrollHandler.next(index);
    }
  }

  /** 处理歌词滚动 */
  private handleLyricScroll(): void {
    this.lyricScrollHandler.subscribe(index => {
      if (!this.lyricElemRefs) {
        this.lyricElemRefs = this.panelScrollList.last.el.nativeElement.querySelectorAll('ul li');
      }
      if (this.lyricElemRefs.length) {
        this.currentLineNum = index;
        // 当歌词行大于歌词滚动开始行时才进行滚动
        if (this.currentLineNum > this.lyricScrollStartLine) {
          this.scrollToCurrentLyric();
        } else {
          this.panelScrollList.last.scrollTo(0, 0);
        }
      }
    });
  }

  private scrollToCurrentSong(speed: number = 20): void {
    const songListRefs = this.panelScrollList.first.el
      .nativeElement.querySelectorAll('ul li');
    if (songListRefs.length) {
      const liElem = songListRefs[this.currentIndex || 0] as HTMLElement;
      const offsetTop = liElem.offsetTop;
      // 单个元素高度
      const offsetHeight = liElem.offsetHeight;
      // 切换歌曲时，进行滚动
      if (offsetTop - Math.abs(this.scrollY) > 8 * offsetHeight
        || offsetTop < Math.abs(this.scrollY)) {
        this.panelScrollList.first.scrollToElement(liElem, speed, false, false);
      }
    }
  }

  private scrollToCurrentLyric(speed = 200): void {
    const targetLine = this.lyricElemRefs[this.currentLineNum - this.lyricScrollStartLine];
    if (targetLine) {
      this.panelScrollList.last.scrollToElement(targetLine, speed, false, false);
    }
  }

  /** 音乐开关控制 */
  private togglePlay(): void {
    const now = Date.now();
    if (this.playing) {
      const startTime = (this.pauseStamp || now) - (this.startStamp || now);
      this.lyricSynchronousScrolled(this.currentLyricLines, startTime);
    } else {
      this.clearTimer();
      this.pauseStamp = now;
    }
  }

  private resetLyricData(): void {
    this.currentLyricLines = [];
    this.currentLineNum = 0;
    this.lyricElemRefs = null;
  }

  /** 清除定时器 */
  private clearTimer() {
    if (this.lyricScrollTimer) {
      this.lyricScrollTimer.unsubscribe();
    }
  }
}
